#ifndef _STATIC_QUEUE_H_
#define _STATIC_QUEUE_H_

#include "Queue.h"
#include "Exception.h"

namespace MySTL
{

template < typename T, int N>
class StaticQueue : public Queue<T>
{
public:
	StaticQueue();
	~StaticQueue();

	bool enqueue(const T& value);
	T dequeue();
	T& top();
	const T& top() const;
	void clear();
	int length() const;
	int capacity() const;

protected:
	T m_array[N];
	int m_length;
	int m_head;
	int m_tail;
};

template < typename T, int N>
StaticQueue<T, N>::StaticQueue()
{
	m_length = 0;
	m_head = 0;
	m_tail = 0;
}

template < typename T, int N>
StaticQueue<T, N>::~StaticQueue()
{
	clear();
}

template < typename T, int N>
bool StaticQueue<T, N>::enqueue(const T& value)
{
	bool ret = (0 <= m_length) && (m_length < N);

	if (ret)
	{
		m_array[m_tail] = value;
		m_tail = (m_tail + 1) % N;
		++m_length;
	}

	return ret;
}

template < typename T, int N>
T StaticQueue<T, N>::dequeue()
{
	if (m_length <= 0)
	{
		THROW_EXCEPTION(InvalidOperationException, "Invalid operate in T StaticQueue<T, N>::dequeue()");
	}

	T ret = m_array[m_head];

	--m_length;
	m_head = (m_head + 1) % N;

	return ret;
}

template < typename T, int N>
T& StaticQueue<T, N>::top()
{
	if (m_length <= 0)
	{
		THROW_EXCEPTION(InvalidOperationException, "Invalid operate in T& StaticQueue<T, N>::top()");
	}

	return m_array[m_head];
}

template < typename T, int N>
const T& StaticQueue<T, N>::top() const
{
	return const_cast<StaticQueue<T, N>*>(this)->top();
}

template < typename T, int N>
void StaticQueue<T, N>::clear()
{
	m_length = 0;
	m_head = 0;
	m_tail = 0;
}

template < typename T, int N>
int StaticQueue<T, N>::length() const
{
	return m_length;
}

template < typename T, int N>
int StaticQueue<T, N>::capacity() const
{
	return N;
}

}

#endif